package redisdemo.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import redisdemo.annotation.RedisCache;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class CacheAspect {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private RedisTemplate redisTemplate;
    //对添加了RedisCache缓存注解的方法才进行缓存
    @Pointcut("@annotation(redisdemo.annotation.RedisCache)")
    public void cache() {

    }
    @Cacheable
    @Around("cache()")
    public Object around(ProceedingJoinPoint point) throws Throwable{
        Object[] args = point.getArgs();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        RedisCache annotation = method.getAnnotation(RedisCache.class);
        for(int i=0;i<args.length;i++)
        {
            if(args[i].getClass()==Class.forName(annotation.className()))
            {
                if(!"".equals(annotation.fieldName()))
                {
                    //如果以对象某个字段做作为key需要进行反射处理
                    Field declaredField = Class.forName(annotation.className()).getDeclaredField(annotation.fieldName());
                    declaredField.setAccessible(true);
                    Object field = declaredField.get(args[i]);
                    if(redisTemplate.opsForValue().get(field.toString())==null)
                    {
                        logger.info("缓存未命中");
                        Object proceed = point.proceed();
                        redisTemplate.opsForValue().set(field,proceed,annotation.minute(), TimeUnit.MINUTES);
                        return proceed;
                    }
                    else
                    {
                        logger.info("命中缓存");
                        return redisTemplate.opsForValue().get(field.toString());
                    }

                }
                else
                {
                    if(redisTemplate.opsForValue().get(args[i].toString())==null)
                    {
                        logger.info("缓存未命中");
                        Object proceed = point.proceed();
                        redisTemplate.opsForValue().set(args[i],proceed,annotation.minute(), TimeUnit.MINUTES);
                        return proceed;
                    }
                    else
                    {
                        logger.info("命中缓存");
                        return redisTemplate.opsForValue().get(args[i].toString());
                    }
                }

            }
        }
        logger.info("没有使用redis缓存");
        //如果没有配置好，还是执行代码
        return point.proceed();
    }
}

